// 版权所有2009 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 包ast声明用于表示Go 
// 包的语法树的类型。
// 
package ast

import (
	"go/token"
	"strings"
)

// ---------------------------------------------------------------
// 接口
// 
// 主要有三类节点：表达式和类型节点、
// 语句节点和声明节点。节点名称通常
// 与它们
// 对应的Go spec产品名称匹配。节点字段对应于各自产品的各个部分
// 。
// 
// 所有节点都包含位置信息，标记
// 对应的源文本段的开头；可通过
// Pos访问器方法访问。对于语言结构，节点可能包含额外的位置信息
// 在结构的
// 部分之间可以找到注释（通常是任何较大的括号子部分）。
// 在打印构造时，正确定位注释需要位置信息。

// 所有节点类型都实现了节点接口。
type Node interface {
	Pos() token.Pos // 属于节点的第一个字符的位置
	End() token.Pos // 紧跟在节点后面的第一个字符的位置
}

// 所有表达式节点都实现Expr接口。
type Expr interface {
	Node
	exprNode()
}

// 所有语句节点都实现Stmt接口。
type Stmt interface {
	Node
	stmtNode()
}

// 所有声明节点都实现Decl接口。
type Decl interface {
	Node
	declNode()
}

// /----------------------------------------------------------------------------------------
// 注释

// 注释节点表示单个
// 
// 文本字段包含注释文本，但不带回车符（\r），因为
// 可能存在于源中。由于注释的结束位置是
// 使用len（Text）计算得出的，因此end（）报告的位置与包含回车符的注释的
// 真正的源结束位置不匹配。
type Comment struct {
	Slash token.Pos // 开始注释的“/”位置
	Text  string    // 注释文本（不包括“\n”表示
}

func (c *Comment) Pos() token.Pos { return c.Slash }
func (c *Comment) End() token.Pos { return token.Pos(int(c.Slash) + len(c.Text)) }

// 注释组表示注释序列
// 之间没有其他标记，也没有空行。
// 
type CommentGroup struct {
	List []*Comment // len（列表）>0 
}

func (g *CommentGroup) Pos() token.Pos { return g.List[0].Pos() }
func (g *CommentGroup) End() token.Pos { return g.List[len(g.List)-1].End() }

func isWhitespace(ch byte) bool { return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' }

func stripTrailingWhitespace(s string) string {
	i := len(s)
	for i > 0 && isWhitespace(s[i-1]) {
		i--
	}
	return s[0:i]
}

// 文本返回注释文本。
// 注释标记（
// 删除前导和尾随空行。
// 注释指令，如“/line”和“/go:noinline”也被删除。
// 将多个空行减少为一行，并修剪行上的尾随空间。
// 除非结果为空，否则换行符终止。
func (g *CommentGroup) Text() string {
	if g == nil {
		return ""
	}
	comments := make([]string, len(g.List))
	for i, c := range g.List {
		comments[i] = c.Text
	}

	lines := make([]string, 0, 10) // 大多数评论少于10行
	for _, c := range comments {
		// 删除评论标记。
		// 解析器准确地给出了注释文本。
		switch c[1] {
		case '/':
			// -风格注释（末尾无换行符）
			c = c[2:]
			if len(c) == 0 {
				// 空行
				break
			}
			if c[0] == ' ' {
				// 删除第一个空格-示例测试需要
				c = c[1:]
				break
			}
			if isDirective(c) {
				// 忽略
				continue
			}
		case '*':
			/*-style comment */
			c = c[2 : len(c)-2]
		}

		// 在换行符上拆分。
		cl := strings.Split(c, "\n")

		// 走行，去掉尾随空白并添加到列表中。
		for _, l := range cl {
			lines = append(lines, stripTrailingWhitespace(l))
		}
	}

	// 删除前导空行；将
	// 内部空行的运行转换为单个空行。
	n := 0
	for _, line := range lines {
		if line != "" || n > 0 && lines[n-1] != "" {
			lines[n] = line
			n++
		}
	}
	lines = lines[0:n]

	// 添加final“”条目以从Join获取尾随换行符。
	if n > 0 && lines[n-1] != "" {
		lines = append(lines, "")
	}

	return strings.Join(lines, "\n")
}

// isDirective报告c是否是注释指令。
func isDirective(c string) bool {
	// /“
	// /（
	if strings.HasPrefix(c, "line ") {
		return true
	}

	// /”
	// /（
	colon := strings.Index(c, ":")
	if colon <= 0 || colon+1 >= len(c) {
		return false
	}
	for i := 0; i <= colon+1; i++ {
		if i == colon {
			continue
		}
		b := c[i]
		if !('a' <= b && b <= 'z' || '0' <= b && b <= '9') {
			return false
		}
	}
	return true
}

// ---------------------------------------------------------------
// 表达式和类型

// 字段表示结构类型中的字段声明列表，
// 接口类型中的方法列表，或签名中的参数/结果声明
// 字段。对于unn，名称为零。）amed参数（仅包含类型的参数列表）
// 和嵌入式结构字段。在后一种情况下，字段名就是类型名。
type Field struct {
	Doc     *CommentGroup // 相关文件；或nil 
	Names   []*Ident      // 字段/方法/（类型）参数名；或nil 
	Type    Expr          // 字段/方法/参数类型；或无
	Tag     *BasicLit     // 字段标记；或无
	Comment *CommentGroup // 行注释；或nil 
}

func (f *Field) Pos() token.Pos {
	if len(f.Names) > 0 {
		return f.Names[0].Pos()
	}
	if f.Type != nil {
		return f.Type.Pos()
	}
	return token.NoPos
}

func (f *Field) End() token.Pos {
	if f.Tag != nil {
		return f.Tag.End()
	}
	if f.Type != nil {
		return f.Type.End()
	}
	if len(f.Names) > 0 {
		return f.Names[len(f.Names)-1].End()
	}
	return token.NoPos
}

// 字段列表表示字段列表，用括号括起来，
// 大括号或方括号。
type FieldList struct {
	Opening token.Pos // 中括号/大括号/括号的位置，如有
	List    []*Field  // 字段列表；或nil 
	Closing token.Pos // 右括号/大括号/括号的位置，如果有
}

func (f *FieldList) Pos() token.Pos {
	if f.Opening.IsValid() {
		return f.Opening
	}
	// 在这种情况下列表不应为空；
	// 保守，防止不良AST 
	if len(f.List) > 0 {
		return f.List[0].Pos()
	}
	return token.NoPos
}

func (f *FieldList) End() token.Pos {
	if f.Closing.IsValid() {
		return f.Closing + 1
	}
	// 在这种情况下，列表不应为空；
	// 保持保守，防止错误的AST 
	if n := len(f.List); n > 0 {
		return f.List[n-1].End()
	}
	return token.NoPos
}

// NumFields返回由字段列表表示的参数或结构字段的数量。
func (f *FieldList) NumFields() int {
	n := 0
	if f != nil {
		for _, g := range f.List {
			m := len(g.Names)
			if m == 0 {
				m = 1
			}
			n += m
		}
	}
	return n
}

// 一个表达式由一个或多个以下具体表达式节点组成的树表示。
// 
type (
	// BadExpr节点是包含
	// 语法错误的表达式的占位符，无法为其创建正确的表达式节点。
	// 
	BadExpr struct {
		From, To token.Pos // 错误表达式的位置范围
	}

	// 标识节点表示标识符。
	Ident struct {
		NamePos token.Pos // 标识符位置
		Name    string    // 标识符名称
		Obj     *Object   // 表示的对象；或者nil 
	}

	// 省略号节点代表“…”输入
	// 参数列表或“…”数组类型中的长度。
	// 
	Ellipsis struct {
		Ellipsis token.Pos // “…”的位置
		Elt      Expr      // 省略号元素类型（仅限参数列表）；或者nil 
	}

	// BasicLit节点表示基本类型的文本。
	BasicLit struct {
		ValuePos token.Pos   // 文字位置
		Kind     token.Token // 标记。INT，令牌。浮动，令牌。伊玛格，代币。或是记号。字符串
		Value    string      // 文本字符串；e、 g.42、0x7f、3.14、1e-9、2.4i、'a'、'\x7f'、'foo'或`\m\n\o`
	}

	// FuncLit节点表示函数文字。
	FuncLit struct {
		Type *FuncType  // 函数类型
		Body *BlockStmt // 函数体
	}

	// 复合文本节点表示复合文本。
	CompositeLit struct {
		Type       Expr      // 文字类型；或者nil 
		Lbrace     token.Pos // 复合元素列表中“{”
		Elts       []Expr    // 的位置；或者nil 
		Rbrace     token.Pos // 如果在Elts列表中缺少（源）表达式
		Incomplete bool      // true。
	}

	// ParenExpr节点表示括号中的表达式，则为“}”
	ParenExpr struct {
		Lparen token.Pos // 位置“（“
		X      Expr      // 括号内的表达式
		Rparen token.Pos // 位置”）”
	}

	// SelectorExpr节点表示后跟选择器的表达式。
	SelectorExpr struct {
		X   Expr   // 表达式
		Sel *Ident // 字段选择器
	}

	// IndexExpr节点表示后跟索引的表达式。
	IndexExpr struct {
		X      Expr      // 表达式
		Lbrack token.Pos // 位置为“[”
		Index  Expr      // 索引表达式
		Rbrack token.Pos // 位置为“]”
	}

	// 一个IndexListExpr节点代表一个表达式，后面跟有多个
	// 索引。
	IndexListExpr struct {
		X       Expr      // 表达式
		Lbrack  token.Pos // 位置为“[”
		Indices []Expr    // 索引表达式
		Rbrack  token.Pos // 位置为“]”
	}

	// 一个切片表达式节点代表一个表达式，后跟切片索引。
	SliceExpr struct {
		X      Expr      // 表达式
		Lbrack token.Pos // 切片范围的开始位置；或nil 
		High   Expr      // 切片范围的结束；或nil 
		Max    Expr      // 切片的最大容量；或nil 
		Slice3 bool      // 如果有三个索引切片（有两个冒号）
		Rbrack token.Pos // 位置“]”
	}

	// 类型断言。
	// 
	TypeAssertExpr struct {
		X      Expr      // 表达式
		Lparen token.Pos // position of“（“
		Type   Expr      // 断言类型；nil表示类型开关X（type）
		Rparen token.Pos // position of”）”
	}

	// 调用方节点表示一个表达式，后跟一个参数列表。
	CallExpr struct {
		Fun      Expr      // 函数表达式
		Lparen   token.Pos // 的位置（（“
		Args     []Expr    // 函数参数）；或nil 
		Ellipsis token.Pos // 的位置“…”（如果没有“…”，则为token.NoPos）
		Rparen   token.Pos // position of”）“
	}

	// StarExpr节点表示“*”表达式形式的表达式。
	// 从语义上讲，它可以是一元“*”表达式，也可以是指针类型。
	// 
	StarExpr struct {
		Star token.Pos // “*”的位置
		X    Expr      // 操作数
	}

	// 一元表达式节点表示一元表达式。
	// 一元“*”表达式通过StarExpr节点表示。
	// 
	UnaryExpr struct {
		OpPos token.Pos   // Op 
		Op    token.Token // 运算符
		X     Expr        // 操作数
	}

	// 二进制表达式节点表示二进制表达式。
	BinaryExpr struct {
		X     Expr        // 左操作数
		OpPos token.Pos   // Op 
		Op    token.Token // 运算符
		Y     Expr        // 右操作数
	}

	// KeyValueExpr节点表示（键：值）对
	// 在复合文字中。
	// 
	KeyValueExpr struct {
		Key   Expr
		Colon token.Pos // 位置：“
		Value Expr
	}
)

// 通道类型的方向由位
// 掩码指示，包括以下一个或两个常量。
// 
type ChanDir int

const (
	SEND ChanDir = 1 << iota
	RECV
)

// 一个类型由一个
// 或多个以下特定于类型的表达式
// 节点组成的树表示。
// 
type (
	// ArrayType节点表示数组或切片类型。
	ArrayType struct {
		Lbrack token.Pos // 位置为“[”
		Len    Expr      // 省略号节点为[…]T数组类型，nil表示切片类型
		Elt    Expr      // 元素类型
	}

	// StructType节点表示结构类型。
	StructType struct {
		Struct     token.Pos  // 关键字“struct”的位置
		Fields     *FieldList // 字段声明列表
		Incomplete bool       // 如果字段列表中缺少（源）字段，则为true 
	}

	// 指针类型通过StarExpr节点表示。

	// FuncType节点代表一个函数类型。
	FuncType struct {
		Func       token.Pos  // func关键字的位置（如果没有“func”，则为token.NoPos）
		TypeParams *FieldList // 类型参数；或无
		Params     *FieldList // （传入）参数；非零
		Results    *FieldList // （传出）结果；或者nil 
	}

	// InterfaceType节点表示接口类型。
	InterfaceType struct {
		Interface  token.Pos  // 接口关键字的位置
		Methods    *FieldList // 嵌入接口、方法或类型的列表
		Incomplete bool       // 如果方法列表中缺少（源）方法或类型
	}

	// 则为true MapType节点表示映射类型。
	MapType struct {
		Map   token.Pos // map关键字的位置
		Key   Expr
		Value Expr
	}

	// 一个ChanType节点代表一个频道类型。
	ChanType struct {
		Begin token.Pos // 关键字“chan”或“<-”（以先到者为准）的位置
		Arrow token.Pos // 关键字“<-”（如果没有“<-”，则为token.NoPos）的位置
		Dir   ChanDir   // 通道方向
		Value Expr      // 值类型
	}
)

// 表达式/类型节点的位置和最终实现。

func (x *BadExpr) Pos() token.Pos  { return x.From }
func (x *Ident) Pos() token.Pos    { return x.NamePos }
func (x *Ellipsis) Pos() token.Pos { return x.Ellipsis }
func (x *BasicLit) Pos() token.Pos { return x.ValuePos }
func (x *FuncLit) Pos() token.Pos  { return x.Type.Pos() }
func (x *CompositeLit) Pos() token.Pos {
	if x.Type != nil {
		return x.Type.Pos()
	}
	return x.Lbrace
}
func (x *ParenExpr) Pos() token.Pos      { return x.Lparen }
func (x *SelectorExpr) Pos() token.Pos   { return x.X.Pos() }
func (x *IndexExpr) Pos() token.Pos      { return x.X.Pos() }
func (x *IndexListExpr) Pos() token.Pos  { return x.X.Pos() }
func (x *SliceExpr) Pos() token.Pos      { return x.X.Pos() }
func (x *TypeAssertExpr) Pos() token.Pos { return x.X.Pos() }
func (x *CallExpr) Pos() token.Pos       { return x.Fun.Pos() }
func (x *StarExpr) Pos() token.Pos       { return x.Star }
func (x *UnaryExpr) Pos() token.Pos      { return x.OpPos }
func (x *BinaryExpr) Pos() token.Pos     { return x.X.Pos() }
func (x *KeyValueExpr) Pos() token.Pos   { return x.Key.Pos() }
func (x *ArrayType) Pos() token.Pos      { return x.Lbrack }
func (x *StructType) Pos() token.Pos     { return x.Struct }
func (x *FuncType) Pos() token.Pos {
	if x.Func.IsValid() || x.Params == nil { // 参见第3870期
		return x.Func
	}
	return x.Params.Pos() // 接口方法声明没有“func”关键字
}
func (x *InterfaceType) Pos() token.Pos { return x.Interface }
func (x *MapType) Pos() token.Pos       { return x.Map }
func (x *ChanType) Pos() token.Pos      { return x.Begin }

func (x *BadExpr) End() token.Pos { return x.To }
func (x *Ident) End() token.Pos   { return token.Pos(int(x.NamePos) + len(x.Name)) }
func (x *Ellipsis) End() token.Pos {
	if x.Elt != nil {
		return x.Elt.End()
	}
	return x.Ellipsis + 3 // len（“…”）
}
func (x *BasicLit) End() token.Pos       { return token.Pos(int(x.ValuePos) + len(x.Value)) }
func (x *FuncLit) End() token.Pos        { return x.Body.End() }
func (x *CompositeLit) End() token.Pos   { return x.Rbrace + 1 }
func (x *ParenExpr) End() token.Pos      { return x.Rparen + 1 }
func (x *SelectorExpr) End() token.Pos   { return x.Sel.End() }
func (x *IndexExpr) End() token.Pos      { return x.Rbrack + 1 }
func (x *IndexListExpr) End() token.Pos  { return x.Rbrack + 1 }
func (x *SliceExpr) End() token.Pos      { return x.Rbrack + 1 }
func (x *TypeAssertExpr) End() token.Pos { return x.Rparen + 1 }
func (x *CallExpr) End() token.Pos       { return x.Rparen + 1 }
func (x *StarExpr) End() token.Pos       { return x.X.End() }
func (x *UnaryExpr) End() token.Pos      { return x.X.End() }
func (x *BinaryExpr) End() token.Pos     { return x.Y.End() }
func (x *KeyValueExpr) End() token.Pos   { return x.Value.End() }
func (x *ArrayType) End() token.Pos      { return x.Elt.End() }
func (x *StructType) End() token.Pos     { return x.Fields.End() }
func (x *FuncType) End() token.Pos {
	if x.Results != nil {
		return x.Results.End()
	}
	return x.Params.End()
}
func (x *InterfaceType) End() token.Pos { return x.Methods.End() }
func (x *MapType) End() token.Pos       { return x.Value.End() }
func (x *ChanType) End() token.Pos      { return x.Value.End() }

// exprNode（）确保只能将表达式/类型节点分配给Expr。
// 
func (*BadExpr) exprNode()        {}
func (*Ident) exprNode()          {}
func (*Ellipsis) exprNode()       {}
func (*BasicLit) exprNode()       {}
func (*FuncLit) exprNode()        {}
func (*CompositeLit) exprNode()   {}
func (*ParenExpr) exprNode()      {}
func (*SelectorExpr) exprNode()   {}
func (*IndexExpr) exprNode()      {}
func (*IndexListExpr) exprNode()  {}
func (*SliceExpr) exprNode()      {}
func (*TypeAssertExpr) exprNode() {}
func (*CallExpr) exprNode()       {}
func (*StarExpr) exprNode()       {}
func (*UnaryExpr) exprNode()      {}
func (*BinaryExpr) exprNode()     {}
func (*KeyValueExpr) exprNode()   {}

func (*ArrayType) exprNode()     {}
func (*StructType) exprNode()    {}
func (*FuncType) exprNode()      {}
func (*InterfaceType) exprNode() {}
func (*MapType) exprNode()       {}
func (*ChanType) exprNode()      {}

// ---------------------------------------------------------------
// 标识的便利功能

// 新标识创建一个没有位置的新标识。
// 对于Go解析器以外的代码生成的AST非常有用。wen jian efg
func NewIdent(name string) *Ident { return &Ident{token.NoPos, name, nil} }

// 
func IsExported(name string) bool { return token.IsExported(name) }

// IsExported报告id是否以大写字母开头。
// 
func (id *Ident) IsExported() bool { return token.IsExported(id.Name) }

func (id *Ident) String() string {
	if id != nil {
		return id.Name
	}
	return "<nil>"
}

// ---------------------------------------------------------------
// 语句

// 一条语句由一个或多个以下具体语句节点组成的树表示。
// 
type (
	// BADSMT节点是包含
	// 语法错误的语句的占位符，无法为其创建正确的语句节点。
	// 
	BadStmt struct {
		From, To token.Pos // 错误语句的位置范围
	}

	// DeclStmt节点表示语句列表中的一个声明。
	DeclStmt struct {
		Decl Decl // /*带有常量、类型或变量标记的GenDecl 
	}

	// 一个EmptyStmt节点代表一个空语句。
	// 空语句的“位置”是紧跟其后（显式或隐式）分号的位置。
	// 
	EmptyStmt struct {
		Semicolon token.Pos // 以下位置”
		Implicit  bool      // 如果设置“；”在源
	}

	// LabeledStmt节点代表一个带标签的语句。
	LabeledStmt struct {
		Label *Ident
		Colon token.Pos // 的位置：“……
		Stmt  Stmt
	}

	// 一个ExprStmt节点代表一个（独立的）表达式
	// 在一个语句列表中。
	// 
	ExprStmt struct {
		X Expr // 表达式
	}

	// sendsmt节点表示send语句。
	SendStmt struct {
		Chan  Expr
		Arrow token.Pos // 位置“<-”
		Value Expr
	}

	// incdecsmt节点表示递增或递减语句。
	IncDecStmt struct {
		X      Expr
		TokPos token.Pos   // Tok 
		Tok    token.Token // INC或DEC 
	}

	// 一个AssignStmt节点代表一个赋值，或
	// 一个短变量声明。
	// 
	AssignStmt struct {
		Lhs    []Expr
		TokPos token.Pos   // Tok的位置
		Tok    token.Token // 分配令牌，定义
		Rhs    []Expr
	}

	// GoStmt节点表示go语句。
	GoStmt struct {
		Go   token.Pos // go关键字的位置
		Call *CallExpr
	}

	// 一个DeferStmt节点代表一个defer语句。
	DeferStmt struct {
		Defer token.Pos // defer关键字的位置
		Call  *CallExpr
	}

	// ReturnStmt节点代表一条return语句。
	ReturnStmt struct {
		Return  token.Pos // 返回关键字
		Results []Expr    // 结果表达式；或nil 
	}

	// BranchStmt节点表示中断、继续、转到、
	// 或故障诊断语句。
	// 
	BranchStmt struct {
		TokPos token.Pos   // Tok的位置
		Tok    token.Token // 关键字标记（中断、继续、转到、故障切换）
		Label  *Ident      // 标签名称；或nil 
	}

	// BlockStmt节点表示带大括号的语句列表。
	BlockStmt struct {
		Lbrace token.Pos // 位置为“{”
		List   []Stmt
		Rbrace token.Pos // 位置为“}”，如果有（可能由于语法错误而缺失）
	}

	// IfStmt节点表示if语句。
	IfStmt struct {
		If   token.Pos // if关键字的位置
		Init Stmt      // 初始化语句；或无
		Cond Expr      // 条件
		Body *BlockStmt
		Else Stmt // 其他分支；或nil 
	}

	// case子句表示表达式或类型开关语句的大小写。
	CaseClause struct {
		Case  token.Pos // case或default关键字的位置
		List  []Expr    // 表达式或类型列表；nil表示默认情况
		Colon token.Pos // 位置为“：”
		Body  []Stmt    // 语句列表；或nil 
	}

	// SwitchStmt节点表示表达式switch语句。
	SwitchStmt struct {
		Switch token.Pos  // 开关关键字的位置
		Init   Stmt       // 初始化语句；或无
		Tag    Expr       // 标记表达式；或者nil 
		Body   *BlockStmt // case子句仅
	}

	// TypeSwitchStmt节点表示类型开关语句。
	TypeSwitchStmt struct {
		Switch token.Pos  // 开关关键字的位置
		Init   Stmt       // 初始化语句；或者nil 
		Assign Stmt       // x:=y.（type）或y.（type）
		Body   *BlockStmt // caseClaimes only 
	}

	// commClaimes节点表示select语句的大小写。
	CommClause struct {
		Case  token.Pos // case或default关键字的位置
		Comm  Stmt      // 发送或接收语句；nil表示默认情况
		Colon token.Pos // 位置为“：”
		Body  []Stmt    // 语句列表；或nil 
	}

	// SelectStmt节点表示select语句。
	SelectStmt struct {
		Select token.Pos  // “select”关键字的位置
		Body   *BlockStmt // COMM子句仅
	}

	// A ForStmt代表for语句。
	ForStmt struct {
		For  token.Pos // 关键字“for”的位置
		Init Stmt      // 初始化语句；或无
		Cond Expr      // 条件；或无
		Post Stmt      // 迭代后语句；或者nil 
		Body *BlockStmt
	}

	// RangeSmt表示带有range子句的for语句。
	RangeStmt struct {
		For        token.Pos   // 关键字“for”的位置
		Key, Value Expr        // 键，值可以为零
		TokPos     token.Pos   // Tok的位置；无效的if Key==nil 
		Tok        token.Token // 非法的if Key==nil，赋值，定义
		X          Expr        // 值以覆盖
		Body       *BlockStmt
	}
)

// Pos和语句节点的结束实现。

func (s *BadStmt) Pos() token.Pos        { return s.From }
func (s *DeclStmt) Pos() token.Pos       { return s.Decl.Pos() }
func (s *EmptyStmt) Pos() token.Pos      { return s.Semicolon }
func (s *LabeledStmt) Pos() token.Pos    { return s.Label.Pos() }
func (s *ExprStmt) Pos() token.Pos       { return s.X.Pos() }
func (s *SendStmt) Pos() token.Pos       { return s.Chan.Pos() }
func (s *IncDecStmt) Pos() token.Pos     { return s.X.Pos() }
func (s *AssignStmt) Pos() token.Pos     { return s.Lhs[0].Pos() }
func (s *GoStmt) Pos() token.Pos         { return s.Go }
func (s *DeferStmt) Pos() token.Pos      { return s.Defer }
func (s *ReturnStmt) Pos() token.Pos     { return s.Return }
func (s *BranchStmt) Pos() token.Pos     { return s.TokPos }
func (s *BlockStmt) Pos() token.Pos      { return s.Lbrace }
func (s *IfStmt) Pos() token.Pos         { return s.If }
func (s *CaseClause) Pos() token.Pos     { return s.Case }
func (s *SwitchStmt) Pos() token.Pos     { return s.Switch }
func (s *TypeSwitchStmt) Pos() token.Pos { return s.Switch }
func (s *CommClause) Pos() token.Pos     { return s.Case }
func (s *SelectStmt) Pos() token.Pos     { return s.Select }
func (s *ForStmt) Pos() token.Pos        { return s.For }
func (s *RangeStmt) Pos() token.Pos      { return s.For }

func (s *BadStmt) End() token.Pos  { return s.To }
func (s *DeclStmt) End() token.Pos { return s.Decl.End() }
func (s *EmptyStmt) End() token.Pos {
	if s.Implicit {
		return s.Semicolon
	}
	return s.Semicolon + 1 /* len(";") */
}
func (s *LabeledStmt) End() token.Pos { return s.Stmt.End() }
func (s *ExprStmt) End() token.Pos    { return s.X.End() }
func (s *SendStmt) End() token.Pos    { return s.Value.End() }
func (s *IncDecStmt) End() token.Pos {
	return s.TokPos + 2 /* len("++") */
}
func (s *AssignStmt) End() token.Pos { return s.Rhs[len(s.Rhs)-1].End() }
func (s *GoStmt) End() token.Pos     { return s.Call.End() }
func (s *DeferStmt) End() token.Pos  { return s.Call.End() }
func (s *ReturnStmt) End() token.Pos {
	if n := len(s.Results); n > 0 {
		return s.Results[n-1].End()
	}
	return s.Return + 6 // len（“return”）
}
func (s *BranchStmt) End() token.Pos {
	if s.Label != nil {
		return s.Label.End()
	}
	return token.Pos(int(s.TokPos) + len(s.Tok.String()))
}
func (s *BlockStmt) End() token.Pos {
	if s.Rbrace.IsValid() {
		return s.Rbrace + 1
	}
	if n := len(s.List); n > 0 {
		return s.List[n-1].End()
	}
	return s.Lbrace + 1
}
func (s *IfStmt) End() token.Pos {
	if s.Else != nil {
		return s.Else.End()
	}
	return s.Body.End()
}
func (s *CaseClause) End() token.Pos {
	if n := len(s.Body); n > 0 {
		return s.Body[n-1].End()
	}
	return s.Colon + 1
}
func (s *SwitchStmt) End() token.Pos     { return s.Body.End() }
func (s *TypeSwitchStmt) End() token.Pos { return s.Body.End() }
func (s *CommClause) End() token.Pos {
	if n := len(s.Body); n > 0 {
		return s.Body[n-1].End()
	}
	return s.Colon + 1
}
func (s *SelectStmt) End() token.Pos { return s.Body.End() }
func (s *ForStmt) End() token.Pos    { return s.Body.End() }
func (s *RangeStmt) End() token.Pos  { return s.Body.End() }

// stmtNode（）确保只能将语句节点分配给Stmt。
// 
func (*BadStmt) stmtNode()        {}
func (*DeclStmt) stmtNode()       {}
func (*EmptyStmt) stmtNode()      {}
func (*LabeledStmt) stmtNode()    {}
func (*ExprStmt) stmtNode()       {}
func (*SendStmt) stmtNode()       {}
func (*IncDecStmt) stmtNode()     {}
func (*AssignStmt) stmtNode()     {}
func (*GoStmt) stmtNode()         {}
func (*DeferStmt) stmtNode()      {}
func (*ReturnStmt) stmtNode()     {}
func (*BranchStmt) stmtNode()     {}
func (*BlockStmt) stmtNode()      {}
func (*IfStmt) stmtNode()         {}
func (*CaseClause) stmtNode()     {}
func (*SwitchStmt) stmtNode()     {}
func (*TypeSwitchStmt) stmtNode() {}
func (*CommClause) stmtNode()     {}
func (*SelectStmt) stmtNode()     {}
func (*ForStmt) stmtNode()        {}
func (*RangeStmt) stmtNode()      {}

// ---------------------------------------------------------------
// 声明

// 规范节点表示单个（非括号）导入，
// 常量、类型或变量声明。
// 
type (
	// 规范类型代表*ImportSpec、*ValueSpec和*TypeSpec中的任何一种。
	Spec interface {
		Node
		specNode()
	}

	// ImportSpec节点代表单个包导入。
	ImportSpec struct {
		Doc     *CommentGroup // 相关文件；或无
		Name    *Ident        // 本地包名（包括“.”）；或nil 
		Path    *BasicLit     // 导入路径
		Comment *CommentGroup // 行注释；或者nil 
		EndPos  token.Pos     // end of spec（如果非零，则覆盖Path.Pos）
	}

	// ValueSpec节点表示常量或变量声明
	// （ConstSpec或VarSpec production）。
	// 
	ValueSpec struct {
		Doc     *CommentGroup // 相关文件；或nil 
		Names   []*Ident      // 值名称（len（names）>0）
		Type    Expr          // 值类型；或零
		Values  []Expr        // 初始值；或无
		Comment *CommentGroup // 行注释；或者nil 
	}

	// TypeSpec节点表示类型声明（TypeSpec生产）。
	TypeSpec struct {
		Doc        *CommentGroup // 相关文件；或nil 
		Name       *Ident        // 类型名称
		TypeParams *FieldList    // 类型参数；或零
		Assign     token.Pos     // 位置“=”，如果有
		Type       Expr          // /*标识、*ParenExpr、*SelectorExpr、*StarExpr或任何*XXX类型
		Comment    *CommentGroup // 行注释；或nil 
	}
)

// spec节点的Pos和End实现。

func (s *ImportSpec) Pos() token.Pos {
	if s.Name != nil {
		return s.Name.Pos()
	}
	return s.Path.Pos()
}
func (s *ValueSpec) Pos() token.Pos { return s.Names[0].Pos() }
func (s *TypeSpec) Pos() token.Pos  { return s.Name.Pos() }

func (s *ImportSpec) End() token.Pos {
	if s.EndPos != 0 {
		return s.EndPos
	}
	return s.Path.End()
}

func (s *ValueSpec) End() token.Pos {
	if n := len(s.Values); n > 0 {
		return s.Values[n-1].End()
	}
	if s.Type != nil {
		return s.Type.End()
	}
	return s.Names[len(s.Names)-1].End()
}
func (s *TypeSpec) End() token.Pos { return s.Type.End() }

// specNode（）确保只能将spec节点
// 分配给spec。
// 
func (*ImportSpec) specNode() {}
func (*ValueSpec) specNode()  {}
func (*TypeSpec) specNode()   {}

// 声明由以下声明节点之一表示。
// 
type (
	// BadDecl节点是包含
	// 语法错误的声明的占位符，无法为其创建正确的声明节点。
	// 
	BadDecl struct {
		From, To token.Pos // 错误声明的位置范围
	}

	// GenDecl节点（泛型声明节点）表示导入，
	// 常量、类型或变量声明。有效的Lparen位置
	// /（Lparen.IsValid（））表示带括号的声明。
	// 
	// Tok值与规格元素类型的关系：
	// 
	// token。IMPORT*ImportSpec 
	// 令牌。CONST*ValueSpec 
	// 令牌。TYPE*TypeSpec 
	// 令牌。VAR*ValueSpec 
	// 
	GenDecl struct {
		Doc    *CommentGroup // 相关文件；或者nil 
		TokPos token.Pos     // Tok的位置
		Tok    token.Token   // IMPORT、CONST、TYPE或VAR 
		Lparen token.Pos     // position of'（'，如果有
		Specs  []Spec
		Rparen token.Pos // position of'），如果有
	}

	// FuncDecl节点代表函数声明。
	FuncDecl struct {
		Doc  *CommentGroup // 相关文件；或无
		Recv *FieldList    // 接收器（方法）；或nil（函数）
		Name *Ident        // 函数/方法名称
		Type *FuncType     // 函数签名：“func”关键字
		Body *BlockStmt    // 函数体的类型和值参数、结果和位置；对于外部（非Go）函数
	}
)

// Pos和声明节点的最终实现，则为nil。

func (d *BadDecl) Pos() token.Pos  { return d.From }
func (d *GenDecl) Pos() token.Pos  { return d.TokPos }
func (d *FuncDecl) Pos() token.Pos { return d.Type.Pos() }

func (d *BadDecl) End() token.Pos { return d.To }
func (d *GenDecl) End() token.Pos {
	if d.Rparen.IsValid() {
		return d.Rparen + 1
	}
	return d.Specs[0].End()
}
func (d *FuncDecl) End() token.Pos {
	if d.Body != nil {
		return d.Body.End()
	}
	return d.Type.End()
}

// declNode（）确保只能将声明节点分配给Decl。
// 
func (*BadDecl) declNode()  {}
func (*GenDecl) declNode()  {}
func (*FuncDecl) declNode() {}

// ---------------------------------------------------------------
// 文件和包

// 文件节点表示Go源文件。
// 
// 注释列表按
// 外观的顺序包含源文件中的所有注释，包括通过文档和注释字段从其他节点指向的注释。
// 
// 为了正确打印包含注释的源代码（使用包
// go/format和go/printer），在修改文件的语法树时，必须特别注意更新注释
// 为了打印，注释根据标记的位置散布在标记之间。如果语法树节点被删除或移动，则其附近的相关注释也必须被删除或相应移动（通过更新其位置）。评论地图可用于促进其中一些操作。
// 
// 注释是否与节点关联以及如何与节点关联取决于操作程序对语法树的解释：除了Doc 
// 和与节点直接关联的注释注释外，其余注释
// 是“自由浮动的”（另见问题#18593，#20744）。
// 
type File struct {
	Doc        *CommentGroup   // 相关文件；或nil 
	Package    token.Pos       // package关键字的位置
	Name       *Ident          // package name 
	Decls      []Decl          // 顶级声明；或者nil 
	Scope      *Scope          // 包作用域（仅此文件）
	Imports    []*ImportSpec   // 导入此文件
	Unresolved []*Ident        // 此文件中未解析的标识符
	Comments   []*CommentGroup // 源文件中所有注释的列表
}

func (f *File) Pos() token.Pos { return f.Package }
func (f *File) End() token.Pos {
	if n := len(f.Decls); n > 0 {
		return f.Decls[n-1].End()
	}
	return f.Name.End()
}

// 包节点表示一组源文件
// 共同构建一个Go包。
// 
type Package struct {
	Name    string             // 包名
	Scope   *Scope             // 所有文件的包范围
	Imports map[string]*Object // 包id映射->包对象
	Files   map[string]*File   // 按文件名转到源文件
}

func (p *Package) Pos() token.Pos { return token.NoPos }
func (p *Package) End() token.Pos { return token.NoPos }
